package com.divemotor.ventarepuestosinternet.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.divemotor.ventarepuestosinternet.dao.ImagenDAO;
import com.divemotor.ventarepuestosinternet.model.Imagen;
import com.divemotor.ventarepuestosinternet.model.Vehiculo;
import com.divemotor.ventarepuestosinternet.util.Constantes;
import com.divemotor.ventarepuestosinternet.util.DatosDeSession;

@SuppressWarnings("unchecked")
@Repository(value = "imagenDAO")
public class ImagenDAOImpl implements ImagenDAO, Serializable {

	private static final long serialVersionUID = 3629422007292532461L;
	
	@Autowired
	private SessionFactory sessionFactory;
	
	@Override
	public List<Imagen> listarImagenesPorSubGrupo(Imagen imagen) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
			.createAlias("imagen.subGrupo", "subGrupo")
			.createAlias("subGrupo.grupo", "grupo")
			
			.add(Restrictions.eq("subGrupo.idSubGrupo", imagen.getSubGrupo().getIdSubGrupo()))
			.add(Restrictions.not(Restrictions.eq("imagen.estado", Constantes.ESTADO_ELIMINADO)))
			.addOrder(Order.asc("orden"));
		return criteria.list();
	}

	@Override
	public List<Imagen> listarImagenesPorSubGrupoYModeloFabrica(Imagen imagen) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
				.createAlias("imagen.subGrupo", "subGrupo")
				.createAlias("subGrupo.grupo", "grupo")
				.createAlias("imagen.modeloFabrica", "modeloFabrica")
				
				.add(Restrictions.eq("subGrupo.idSubGrupo", imagen.getSubGrupo().getIdSubGrupo()))
				.add(Restrictions.eq("modeloFabrica.modeloFabricaPK.idModeloFabrica",
						imagen.getModeloFabrica().getModeloFabricaPK().getIdModeloFabrica()))
				.add(Restrictions.eq("modeloFabrica.modeloFabricaPK.idMarca",
						imagen.getModeloFabrica().getModeloFabricaPK().getIdMarca()))
				.add(Restrictions.eq("modeloFabrica.modeloFabricaPK.idTipoComponente",
						imagen.getModeloFabrica().getModeloFabricaPK().getIdTipoComponente()))
				.add(Restrictions.not(Restrictions.eq("imagen.estado", Constantes.ESTADO_ELIMINADO)))
				.addOrder(Order.asc("imagen.orden"));
		return criteria.list();
	}

	@Override
	public String obtenerMaximoNombreImagen() {
		Query query = sessionFactory.getCurrentSession().createQuery("SELECT MAX(nombreArchivo) FROM Imagen");
		String nombreImagen = (String) query.list().get(0);
		if (nombreImagen == null) {
			nombreImagen = Constantes.PRIMER_NOMBRE_IMAGEN;
		}
		return nombreImagen;
	}

	@Override
	public Integer obtenerMaximoIdImagen() {
		Query query = sessionFactory.getCurrentSession().createQuery("SELECT MAX(id) FROM Imagen");
		return (Integer) query.list().get(0);
	}

	@Override
	public Imagen insertar(Imagen imagen) {
		sessionFactory.getCurrentSession().persist(imagen);
		return imagen;
	}

	@Override
	public void eliminar(Imagen imagen) {
		sessionFactory.getCurrentSession().delete(imagen);
	}

	@Override
	public List<Imagen> listarImagenesPorSubGrupoYTipoComponente(Imagen imagen) {
		Criteria criteriaIdsImagenes = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
				.createAlias("imagen.subGrupo", "subGrupo")
				.createAlias("subGrupo.grupo", "grupo")
				.createAlias("imagen.modeloFabrica", "modeloFabrica")
				.createAlias("modeloFabrica.tipoComponente", "tipoComponente")
				.setProjection(Projections.projectionList().add(Projections.distinct(Projections.property("imagen.idImagen"))))
				
				.add(Restrictions.eq("subGrupo.idSubGrupo", imagen.getSubGrupo().getIdSubGrupo()))
				.add(Restrictions.eq("tipoComponente.idTipoComponente", imagen.getModeloFabrica().getTipoComponente().getIdTipoComponente()))
				.add(Restrictions.eq("imagen.estado", Constantes.ESTADO_ACTIVO));
		
		List<Integer> listaIdsImagenes = criteriaIdsImagenes.list();
		
		if (listaIdsImagenes != null && listaIdsImagenes.size() != 0) {
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
					.add(Restrictions.in("imagen.idImagen", listaIdsImagenes))
					.addOrder(Order.asc("imagen.idImagen"));
			return criteria.list();
		} else {
			return new ArrayList<Imagen>();
		}
		
	}

	@Override
	public List<Imagen> listarImagenesPorMarcaSubGrupoYTipoComponente(Imagen imagen) {
		Criteria criteriaIdsImagenes = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
				.createAlias("imagen.subGrupo", "subGrupo")
				.createAlias("subGrupo.grupo", "grupo")
				.createAlias("imagen.modeloFabrica", "modeloFabrica")
				.createAlias("modeloFabrica.tipoComponente", "tipoComponente")
				.createAlias("modeloFabrica.marca", "marca")
				.setProjection(Projections.projectionList().add(Projections.distinct(Projections.property("imagen.idImagen"))))
				.add(Restrictions.eq("grupo.pais", DatosDeSession.obtenerPaisDelUsuarioAutenticado()))
				.add(Restrictions.eq("subGrupo.idSubGrupo", imagen.getSubGrupo().getIdSubGrupo()))
				.add(Restrictions.eq("tipoComponente.idTipoComponente", imagen.getModeloFabrica().getTipoComponente().getIdTipoComponente()))
				.add(Restrictions.eq("marca.codigoMarca", imagen.getModeloFabrica().getMarca().getCodigoMarca()))
				.add(Restrictions.eq("imagen.estado", Constantes.ESTADO_ACTIVO));
		
		List<Integer> listaIdsImagenes = criteriaIdsImagenes.list();
		
		if (listaIdsImagenes != null && listaIdsImagenes.size() != 0) {
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
					.add(Restrictions.in("imagen.idImagen", listaIdsImagenes))
					.addOrder(Order.asc("imagen.idImagen"));
			return criteria.list();
		} else {
			return new ArrayList<Imagen>();
		}
	}
	
	@Override
	public List<Imagen> listarImagenesPorMarcaSubGrupoYTipoComponenteYVehiculo(Imagen imagen, Vehiculo vehiculo) {
		Criteria criteriaIdsImagenes = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
				.createAlias("imagen.subGrupo", "subGrupo")
				.createAlias("subGrupo.grupo", "grupo")
				.createAlias("imagen.modeloFabrica", "modeloFabrica")
				.createAlias("modeloFabrica.listaVehiculoModeloFabrica", "vehiculoModeloFabrica")
				.createAlias("vehiculoModeloFabrica.vehiculo", "vehiculo")
				.createAlias("modeloFabrica.tipoComponente", "tipoComponente")
				.createAlias("modeloFabrica.marca", "marca")
				.setProjection(Projections.projectionList().add(Projections.distinct(Projections.property("imagen.idImagen"))))
				
				.add(Restrictions.eq("subGrupo.idSubGrupo", imagen.getSubGrupo().getIdSubGrupo()))
				.add(Restrictions.eq("tipoComponente.idTipoComponente", imagen.getModeloFabrica().getTipoComponente().getIdTipoComponente()))
				.add(Restrictions.eq("imagen.estado", Constantes.ESTADO_ACTIVO))
				.add(Restrictions.eq("vehiculo.chasis", vehiculo.getChasis()));
		
		List<Integer> listaIdsImagenes = criteriaIdsImagenes.list();
		
		if (listaIdsImagenes != null && listaIdsImagenes.size() != 0) {
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Imagen.class, "imagen")
					.add(Restrictions.in("imagen.idImagen", listaIdsImagenes))
					.addOrder(Order.asc("imagen.idImagen"));
			return criteria.list();
		} else {
			return new ArrayList<Imagen>();
		}
	}

	@Override
	public Imagen obtenerPorId(Imagen imagen) {
		return (Imagen) sessionFactory.getCurrentSession().get(Imagen.class, imagen.getIdImagen());
	}

	@Override
	public void cambiarOrdenImagenes(int ordenInicial, int ordenFinal, int incremento) {
		sessionFactory
			.getCurrentSession()
			.createQuery(
					"update Imagen set orden = orden +(:incremento) " + 
					"where orden >= :ordenInicial and " + 
					"orden <= :ordenFinal and " + 
					"estado <> :estadoInactivo")
			.setParameter("incremento", new Integer(incremento))
			.setParameter("ordenInicial", new Integer(ordenInicial))
			.setParameter("ordenFinal", new Integer(ordenFinal))
			.setParameter("estadoInactivo", Constantes.ESTADO_ELIMINADO)
			.executeUpdate();
	}

	@Override
	public void actualizar(Imagen imagen) {
		sessionFactory.getCurrentSession().merge(imagen);
	}

}
